package com.symaster.common.geom.show.map.create;

import com.symaster.common.geom.entity.LineSegment;
import com.symaster.common.geom.entity.Point;
import com.symaster.common.geom.util.PointUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class EditController extends MouseAdapter {
    public final MapCreateView mapCreateView;
    private final Point startControllerPoint;
    private final Set<LineSegment> ignoreLines;

    public Status status = Status.NORMAL;

    public EditController(MapCreateView mapCreateView) {
        this.mapCreateView = mapCreateView;
        this.ignoreLines = new HashSet<>();
        this.startControllerPoint = new Point(0, 0);
    }

    public void setToolBarButtonEnable(boolean enable) {
        JToolBar toolBar = mapCreateView.getToolBar();
        for (Component component : toolBar.getComponents()) {
            if (component instanceof JButton) {
                component.setEnabled(enable);
            }
        }
    }

    public void updateMessage(String message) {
        mapCreateView.message = message;
    }

    public void createLine() {
        if (this.status == Status.NORMAL) {
            this.status = Status.CREATE_LINE;
            setToolBarButtonEnable(false);
            updateMessage("创建直线, 单击左键选择起始点, 单击右键取消创建");
        }
    }

    public void createCurve() {
        if (this.status == Status.NORMAL) {
            this.status = Status.CREATE_CURVE;
            setToolBarButtonEnable(false);
            updateMessage("创建曲线, 单击左键选择起始点, 单击右键取消创建");
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        this.status.mousePressed(e, this);
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        this.status.magnet(e, this);
        this.status.mouseMoved(e, this);
    }

    public enum Status {
        CREATE_LINE {
            private LineSegment createLineSegment;
            public int createLineStep = 0;

            @Override
            public void mousePressedLeft(MouseEvent e, EditController editController) {
                Point point = editController.startControllerPoint;
                if (createLineStep == 0) {

                    editController.updateMessage("创建直线, 单击左键选择第二个点, 单击右键撤销第一点");
                    createLineSegment = new LineSegment(new Point(point.getX(), point.getY()), new Point(point.getX(), point.getY()));
                    editController.ignoreLines.add(createLineSegment);
                    editController.mapCreateView.putLineSegment(createLineSegment);
                    createLineStep = 1;
                } else if (createLineStep == 1) {
                    createLineStep = 0;
                    Point endPoint = createLineSegment.getEndPoint();
                    endPoint.setX(point.getX());
                    endPoint.setY(point.getY());
                    if (createLineSegment.length() < 1) {
                        editController.mapCreateView.removeLineSegment(createLineSegment);
                    }
                    editController.ignoreLines.remove(createLineSegment);
                    editController.updateMessage("创建直线, 单击左键选择起始点, 单击右键取消创建");
                }
            }

            @Override
            public void mousePressedRight(MouseEvent e, EditController editController) {
                if (createLineStep == 0) {
                    editController.status = Status.NORMAL;
                    editController.startControllerPoint.setX(0);
                    editController.startControllerPoint.setY(0);
                    createLineStep = 0;
                    editController.setToolBarButtonEnable(true);
                    editController.updateMessage(null);
                    editController.ignoreLines.remove(createLineSegment);

                } else if (createLineStep == 1) {
                    editController.mapCreateView.removeLineSegment(createLineSegment);
                    createLineStep = 0;
                }
            }

            @Override
            public void mouseMoved(MouseEvent e, EditController editController) {
                Point point = editController.startControllerPoint;
                if (createLineStep == 1) {
                    Point endPoint = createLineSegment.getEndPoint();
                    endPoint.setX(point.getX());
                    endPoint.setY(point.getY());
                }
            }
        },
        CREATE_CURVE {
            public int createLineStep = 0;
            private Set<LineSegment> createLineSegment;

            @Override
            public void mousePressedLeft(MouseEvent e, EditController editController) {
                if (createLineStep == 0) {

                    createLineStep = 1;
                } else if (createLineStep == 1) {
                    createLineStep = 2;
                } else if (createLineStep == 2) {
                    createLineStep = 0;
                }
            }

            @Override
            public void mousePressedRight(MouseEvent e, EditController editController) {
                super.mousePressedRight(e, editController);
            }

            @Override
            public void mouseMoved(MouseEvent e, EditController editController) {

            }
        },
        NORMAL {
        },

        ;

        public final void mousePressed(MouseEvent e, EditController editController) {
            int button = e.getButton();
            if (button == 3) {
                mousePressedRight(e, editController);
            } else if (button == 2) {
                mousePressedCenter(e, editController);
            } else if (button == 1) {
                mousePressedLeft(e, editController);
            }
        }

        protected void mousePressedLeft(MouseEvent e, EditController editController) {

        }

        protected void mousePressedCenter(MouseEvent e, EditController editController) {

        }

        protected void mousePressedRight(MouseEvent e, EditController editController) {

        }

        public void mouseMoved(MouseEvent e, EditController editController) {

        }

        public void magnet(MouseEvent e, EditController editController) {
            Set<LineSegment> lineSegments = editController.mapCreateView.getLineSegments().stream().filter(e2 -> !editController.ignoreLines.contains(e2)).collect(Collectors.toSet());

            Set<Point> points = new HashSet<>();
            for (LineSegment lineSegment : lineSegments) {
                points.add(lineSegment.getStartPoint());
                points.add(lineSegment.getEndPoint());
                points.add(lineSegment.center());
            }

            List<Point> collect = points.stream().sorted((o1, o2) -> {
                double o1L = PointUtil.getTranslateVector(e.getX(), e.getY(), o1.getX(), o1.getY()).length();
                double o2L = PointUtil.getTranslateVector(e.getX(), e.getY(), o2.getX(), o2.getY()).length();
                return Double.compare(o1L, o2L);
            }).collect(Collectors.toList());

            Point point;
            if (!collect.isEmpty() &&
                    (point = collect.get(0)) != null &&
                    PointUtil.getTranslateVector(e.getX(), e.getY(), point.getX(), point.getY()).length() <= 5) {
                editController.startControllerPoint.setX(point.getX());
                editController.startControllerPoint.setY(point.getY());
                editController.mapCreateView.putControllerPoint(editController.startControllerPoint);
            } else {
                editController.startControllerPoint.setX(e.getX());
                editController.startControllerPoint.setY(e.getY());
                editController.mapCreateView.removeControllerPoint(editController.startControllerPoint);
            }
        }


    }
}